package com.xmxsuperstar.app.client.twitter.oauth;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.UUID;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import net.love5z.common.codec.Base64;
import net.love5z.common.utils.SHA256Util;
import net.love5z.common.utils.URLUtils;
import android.util.Log;

import com.xmxsuperstar.app.client.ClientConstants;
import com.xmxsuperstar.http.HttpQueryParams;

public class OAuth {

	private final String consumerSecret;
	private final String consumerKey;
	private final String accessToken;
	private final String accessTokenSecret;
	private final String nonce;
	private final String version = "1.0";
	private final String timestamp;
	private final String signatureMethod = "HMAC-SHA1";

	public OAuth(String accessToken, String accessTokenSecret,
			String consumerKey, String consumerSecret) {

		this.accessToken = accessToken;
		this.accessTokenSecret = accessTokenSecret;
		this.consumerKey = consumerKey;
		this.consumerSecret = consumerSecret;

		this.nonce = this.getOAuthNonce();
		this.timestamp = this.getOAuthTimestamp();
	}

	protected String getOAuthNonce() {
		String randKey = UUID.randomUUID().toString() + "_"
				+ System.currentTimeMillis();
		String s = SHA256Util.hash(randKey);
		return s;
		// return "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y";
	}

	protected String getOAuthTimestamp() {
		Date date = new Date();
		long time = date.getTime();
		return String.valueOf(time / 1000);
		// return "1272325550";
	}

	protected String hmacsha1(String data, String key) {
		byte[] byteHMAC = null;
		try {
			Mac mac = Mac.getInstance("HmacSHA1");
			SecretKeySpec spec = new SecretKeySpec(key.getBytes(), "HmacSHA1");
			mac.init(spec);
			byteHMAC = mac.doFinal(data.getBytes());
		} catch (InvalidKeyException e) {
			Log.e(ClientConstants.LogTag, e.getMessage());
		} catch (NoSuchAlgorithmException ignore) {
			Log.e(ClientConstants.LogTag, ignore.getMessage());
		}
		String oauth = Base64.encode(byteHMAC);
		return oauth;
	}

	protected String createBaseString(String httpMethod, String endPoint,
			HttpQueryParams params) {

		StringBuilder baseString = new StringBuilder(
				URLUtils.urlEncode(httpMethod));

		baseString.append("&").append(URLUtils.urlEncode(endPoint));

		int i = 0;
		for (String key : params.getAllKeys()) {
			for (String value : params.get(key)) {
				String join = URLUtils.urlEncode("&");
				if (i == 0)
					join = "&";
				baseString.append(join).append(URLUtils.urlEncode(key))
						.append(URLUtils.urlEncode("="))
						.append(URLUtils.urlEncode(value));
				i++;
			}

		}

		return baseString.toString();
	}

	protected String getOAuthSignature(String httpMethod, String endPoint,
			HttpQueryParams params) {
		params.add("oauth_consumer_key", this.consumerKey);
		params.add("oauth_nonce", this.nonce);
		params.add("oauth_signature_method", this.signatureMethod);
		params.add("oauth_token", this.accessToken);
		params.add("oauth_timestamp", this.timestamp);
		params.add("oauth_version", this.version);

		String base = this.createBaseString(httpMethod, endPoint, params);

		Log.i(ClientConstants.LogTag, "base string: " + base);

		String key = URLUtils.urlEncode(this.consumerSecret) + "&"
				+ URLUtils.urlEncode(this.accessTokenSecret);

		return this.hmacsha1(base, key);
	}

	public String getAuthorizationHeaderContent(String httpMethod,
			String endPoint, HttpQueryParams params) {
		StringBuilder authorization = new StringBuilder();

		authorization.append("OAuth").append(" ");
		authorization.append("oauth_nonce").append("=\"")
				.append(URLUtils.urlEncode(this.nonce)).append("\"");
		authorization.append(",").append(" ").append("oauth_signature_method")
				.append("=\"").append(URLUtils.urlEncode(this.signatureMethod))
				.append("\"");
		authorization.append(",").append(" ").append("oauth_timestamp")
				.append("=\"").append(URLUtils.urlEncode(this.timestamp))
				.append("\"");
		authorization.append(",").append(" ").append("oauth_consumer_key")
				.append("=\"").append(URLUtils.urlEncode(this.consumerKey))
				.append("\"");
		authorization.append(",").append(" ").append("oauth_token")
				.append("=\"").append(URLUtils.urlEncode(this.accessToken))
				.append("\"");
		authorization
				.append(",")
				.append(" ")
				.append("oauth_signature")
				.append("=\"")
				.append(URLUtils.urlEncode(this.getOAuthSignature(httpMethod,
						endPoint, params))).append("\"");
		authorization.append(",").append(" ").append("oauth_version")
				.append("=\"").append(URLUtils.urlEncode(this.version))
				.append("\"");

		return authorization.toString();
	}

}
